package com.zh.risk.quartz.merchant;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;


import com.ql.util.express.DefaultContext;
import com.ql.util.express.ExpressRunner;
import com.ql.util.express.IExpressContext;
import com.zh.risk.dao.RiskCornDao;
import com.zh.risk.entity.RiskBlackList;
import com.zh.risk.entity.RiskMerchTrans;
import com.zh.risk.quartz.ab.GetSqlTemplateAdapter;
import com.zh.risk.quartz.ab.GetSqlTemplateRunningAdapter;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import com.zh.common.util.DateSetUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.BulkOperations;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.data.util.Pair;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.*;

import static com.zh.risk.RiskConstants.TRANS_DB_API_NAME;

/**
 * code is far away from bug with the animal protecting
 * ┏┓　　　┏┓
 * ┏┛┻━━━┛┻┓
 * ┃　　　　　　　┃
 * ┃　　　━　　　┃
 * ┃　┳┛　┗┳　┃
 * ┃　　　　　　　┃
 * ┃　　　┻　　　┃
 * ┃　　　　　　　┃
 * ┗━┓　　　┏━┛
 * 　　┃　　　┃神兽保佑
 * 　　┃　　　┃代码无BUG！
 * 　　┃　　　┗━━━┓
 * 　　┃　　　　　　　┣┓
 * 　　┃　　　　　　　┏┛
 * 　　┗┓┓┏━┳┓┏┛
 * 　　　┃┫┫　┃┫┫
 * 　　　┗┻┛　┗┻┛
 *
 * @Description: 风控实现
 * @Author: Liard
 * @Create in: 2020/7/14 18:15
 * @Version: 1.0.1
 */
@Component
@Slf4j
public class GetSqlTemplate implements GetSqlTemplateAdapter, GetSqlTemplateRunningAdapter {

    private static GetSqlTemplate getSqlTemplate;

    @Contract(pure = true)
    public static GetSqlTemplate getInstance() {
        return getSqlTemplate;
    }

    @Autowired
    private MongoTemplate mongoTemplate;

    @Autowired
    private RiskCornDao riskCornDao;

    @PostConstruct
    public void init() {
        getSqlTemplate = this;
    }


    @Override
    public String modMrcRisk(@NotNull RiskMerchTrans riskMrc) throws Exception {
        String tpl = "";
        String param = "";
        log.info("###### 开始统计{}信息。模板信息: {}", riskMrc.getName(), tpl);
        log.info("###### 开始统计{}信息。参数信息: {}", riskMrc.getName(), param);
        HashMap paramMap = JSON.parseObject(param, HashMap.class);
        ExpressRunner runner = QlRunner.getInstance().getRunner();
        // 从模板中查询出设定好的需要统计的天数信息
        String date = DateSetUtil.getDateByNum(Integer.parseInt(paramMap.get("day").toString()));
        // 根据天数查询调用修改费率接口的次数信息
        Query query = new Query(Criteria.where("tags").is(riskMrc.getMethodName()).and("startDate").gte(date));
        List<Map> ans = mongoTemplate.find(query, Map.class, TRANS_DB_API_NAME);
        int i = ans.size();
        // 设置上下文环境,该方法中必填两个参数
        IExpressContext<String, Object> expressContext = new DefaultContext<String, Object>();
        expressContext.put("预定次数", paramMap.get("count"));
        expressContext.put("实际次数", i);
        expressContext.put("符合分数", paramMap.get("s_score"));
        expressContext.put("异常分数", paramMap.get("e_score"));
        // 执行表达式
        String d = (String) runner.execute(tpl, expressContext, null, false, false);
        log.info("得分：{}", d);
        return d;
    }

    @Override
    public String modMrcName(@NotNull RiskMerchTrans riskMrc) throws Exception {
        String tpl = "";
        String param = "";
        log.info("###### 开始统计{}规则信息。模板信息: {}", riskMrc.getName(), tpl);
        log.info("###### 开始统计{}规则信息。参数信息: {}", riskMrc.getName(), param);
        HashMap paramMap = JSON.parseObject(tpl, HashMap.class);
        ExpressRunner runner = QlRunner.getInstance().getRunner();
        // 从模板中查询出设定好的需要统计的天数信息
        String date = DateSetUtil.getDateByNum(Integer.parseInt(paramMap.get("day").toString()));
        // 根据天数查询调用修改费率接口的次数信息
        Query query = new Query(Criteria.where("tags").is(riskMrc.getMethodName()).and("startDate").gte(date));
        List<Map> ans = mongoTemplate.find(query, Map.class, TRANS_DB_API_NAME);
        int i = ans.size();
        // 设置上下文环境,该方法中必填两个参数
        IExpressContext<String, Object> expressContext = new DefaultContext<String, Object>();
        expressContext.put("预定次数", paramMap.get("count"));
        expressContext.put("实际次数", i);
        expressContext.put("符合分数", paramMap.get("s_score"));
        expressContext.put("异常分数", paramMap.get("e_score"));
        // 执行表达式
        String d = (String) runner.execute(tpl, expressContext, null, false, false);
        log.info("得分：{}", d);
        return d;
    }

    @Override
    public void ipCheck(@NotNull RiskMerchTrans riskMrc) throws Exception {
        // 获取高风险地区和敏感黑名单列表
        List<RiskBlackList> areaList = riskCornDao.getBlackTransList(new RiskBlackList(7));
        // 获取敏感地区黑名单列表
        List<RiskBlackList> sensList = riskCornDao.getBlackTransList(new RiskBlackList(8));
        List<RiskBlackList> list = new ArrayList<>();
        list.addAll(areaList);
        list.addAll(sensList);
        List<Pair<Query, Update>> updateList = new ArrayList<>(list.size());
        list.forEach(item -> {
            Query query = new Query(new Criteria("riskObj").is(item.getRiskObj()));
            Update update = new Update();
            update.set("description", item.getDescription());
            update.set("riskObj", item.getRiskObj());
            update.set("type", item.getType());
            update.set("addTime", DateUtil.now());
            Pair<Query, Update> pair = Pair.of(query, update);
            updateList.add(pair);
        });
        BulkOperations bulkOp = this.mongoTemplate.bulkOps(BulkOperations.BulkMode.UNORDERED, RiskBlackList.class);
        bulkOp.upsert(updateList);
        bulkOp.execute();
    }

    @Override
    public String mrcTypeAmtRisk(@NotNull RiskMerchTrans riskMrc) throws Exception {
        log.info("###### 开始统计{}规则信息。", riskMrc.getName());

        return null;
    }

    @Override
    public String transTimeErr(@NotNull RiskMerchTrans riskMrc) throws Exception {
        log.info("###### 开始统计{}规则信息。", riskMrc.getName());
        return null;
    }

    @Override
    public String addTransAmtErr(@NotNull RiskMerchTrans riskMrc) throws Exception {
        log.info("###### 开始统计{}规则信息。", riskMrc.getName());
        return null;
    }

    @Override
    public String transFluctuate(@NotNull RiskMerchTrans riskMrc) throws Exception {
        log.info("###### 开始统计{}规则信息。", riskMrc.getName());
        return null;
    }

    @Override
    public Boolean disAreaCheck(@NotNull RiskMerchTrans riskMrc) throws Exception {
        log.info("###### 开始统计{}规则信息。", riskMrc.getName());
        return null;
    }

    @Override
    public Boolean areaCheck(@NotNull RiskMerchTrans riskMrc) throws Exception {
        log.info("###### 开始统计{}规则信息。", riskMrc.getName());
        return null;
    }

    @Override
    public Boolean blackList(@NotNull RiskMerchTrans riskMrc) throws Exception {
        log.info("###### 开始统计{}规则信息。", riskMrc.getName());
        return null;
    }

    @Override
    public Boolean transErr(@NotNull RiskMerchTrans riskMrc) throws Exception {
        log.info("###### 开始统计{}规则信息。", riskMrc.getName());
        return null;
    }

    @Override
    public Boolean repTrans(@NotNull RiskMerchTrans riskMrc) throws Exception {
        log.info("###### 开始统计{}规则信息。", riskMrc.getName());
        return null;
    }

    @Override
    public Boolean humanAudit(@NotNull RiskMerchTrans riskMrc) throws Exception {
        log.info("###### 开始统计{}规则信息。", riskMrc.getName());
        return null;
    }
}
